/**
 * 语音合成模块类，负责处理在线语音合成的相关操作。
 *
 * @author linxiongjun
 * @date 2025-05-29
 */
package com.asr.plugin_asr

import android.media.AudioFormat
import android.media.AudioManager
import android.media.AudioTrack
import com.asr.plugin_asr.ktx.log
import com.asr.plugin_asr.params.PersonTTSParams
import com.iflytek.sparkchain.core.tts.PersonateTTS
import com.iflytek.sparkchain.core.tts.TTS
import com.iflytek.sparkchain.core.tts.TTSCallbacks

/**
 * 语音合成类，封装了讯飞在线语音合成的初始化、启动和停止功能。
 */
class SpeechPersonSynthesis {
    // 讯飞在线TTS实例，使用可空类型并延迟初始化
    private var personateTTS: PersonateTTS? = null

    // TTS参数配置
    private val tTSParams = PersonTTSParams()

    // 是否正在播放音频
    @Volatile
    private var isPlaying = false

    // AudioTrack实例，使用可空类型并延迟初始化
    private var audioTrack: AudioTrack? = null

    // 音频通道配置：单声道
    private val channelConfig: Int = AudioFormat.CHANNEL_OUT_MONO

    // 音频编码格式：PCM 16位
    private val audioFormat: Int = AudioFormat.ENCODING_PCM_16BIT

    private var ttsEndCallback: ((Int) -> Unit)? = null

    /**
     * 开始在线语音合成并播放音频。
     *
     * @param text 要合成的文本
     * @return 合成结果，0表示成功，非0表示失败
     */
    fun startPersonTTS(text: String, ttsEndCallback: (result: Int) -> Unit): Int {
        this.ttsEndCallback = ttsEndCallback
        // 如果正在播放音频，则先停止
        if (isPlaying) {
            stopPersonTTS()
            stopAudioTrack()
        }

        // 初始化或重新开始AudioTrack
        ensureAudioTrackInitialized()

        // 配置TTS参数
        configureTTS()

        // 注册TTS回调函数
        registerTTSCallbacks()

        // 开始语音合成
        "开始语音合成：$text".log()
        val ret = personateTTS!!.aRun(text)
        if (ret == 0) {
            isPlaying = true
        } else {
            isPlaying = false
            this.ttsEndCallback = null
        }
        return ret
    }

    /**
     * 开始流式在线语音合成并播放音频。
     *
     * @param text 要合成的单个文本
     * status 输入文本状态，0:开始，1:中间，2:结束
     * @return 合成结果，0表示成功，非0表示失败
     */
    fun startFlowPersonTTS(text: String, status: Int, ttsEndCallback: (result: Int) -> Unit): Int {
        if(status == 2) {
            this.ttsEndCallback = ttsEndCallback
        } else {
            this.ttsEndCallback = null
        }
        // 如果正在播放音频，则先停止
        if (status == 0) {
            if (isPlaying) {
                stopPersonTTS()
                stopAudioTrack()
            }

            // 初始化或重新开始AudioTrack
            ensureAudioTrackInitialized()

            // 配置TTS参数
            configureTTS()

            // 注册TTS回调函数
            registerTTSCallbacks()

            // 开始语音合成
            "开始语音合成：$text".log()
        }
        val ret = personateTTS!!.aRun(text, status)
        if (ret == 0) {
            isPlaying = true
        } else if(status == 2) {
            isPlaying = false
            this.ttsEndCallback = null
        } else {
            isPlaying = false
        }
        return ret
    }

    /**
     * 确保AudioTrack已初始化并开始播放
     */
    private fun ensureAudioTrackInitialized() {
        if (audioTrack == null) {
            val minBufferSize = AudioTrack.getMinBufferSize(
                tTSParams.rate,
                channelConfig,
                audioFormat
            )
            audioTrack = AudioTrack(
                AudioManager.STREAM_MUSIC,
                tTSParams.rate,
                channelConfig,
                audioFormat,
                minBufferSize,
                AudioTrack.MODE_STREAM
            ).apply {
                play()
            }
        } else {
            audioTrack?.play()
        }
    }

    /**
     * 配置TTS参数
     */
    private fun configureTTS() {
        personateTTS = PersonateTTS(tTSParams.vcn).apply {
            speed(tTSParams.speed)
            pitch(tTSParams.pitch)
            volume(tTSParams.volume)
            sparkAssist(true)
            oralLevel(tTSParams.oralLevel)
            sampleRate(tTSParams.rate)
        }
    }

    /**
     * 注册TTS回调函数
     */
    private fun registerTTSCallbacks() {
        personateTTS?.registerCallbacks(object : TTSCallbacks {
            /**
             * 合成结果回调
             *
             * @param result 合成结果对象
             * @param p1 额外参数（通常为null）
             */
            override fun onResult(result: TTS.TTSResult?, p1: Any?) {
                result?.data?.let { audioData ->
                    if (audioTrack != null && audioData.isNotEmpty()) {
                        audioTrack!!.write(audioData, 0, audioData.size)
                    }
                }

                result?.status?.let { status ->
                    if (status == 2) {
                        "语音合成并播放完成".log()
                        stopAudioTrack()
                        // 通知调用者音频播放完成
                        if (ttsEndCallback != null) {
                            ttsEndCallback!!(0)
                            ttsEndCallback = null
                        }
                    }
                }
            }

            /**
             * 错误回调
             *
             * @param error 错误对象
             * @param p1 额外参数（通常为null）
             */
            override fun onError(error: TTS.TTSError, p1: Any?) {
                val msg = "合成出错！code:${error.code},msg:${error.errMsg},sid:${error.sid}"
                msg.log()
                stopAudioTrack()
            }
        })
    }

    /**
     * 停止在线语音合成。
     */
    fun stopPersonTTS() {
        personateTTS?.stop()?.also {
            personateTTS = null
        }
    }

    /**
     * 停止音频播放并释放资源。
     */
    fun stopAudioTrack() {
        audioTrack?.apply {
            stop()
            release()
            audioTrack = null
        }
        isPlaying = false
    }

    /**
     * 释放所有资源
     */
    fun release() {
        "释放所有资源".log()
        if (ttsEndCallback != null) {
            ttsEndCallback!!(1)
            ttsEndCallback = null
        }
        stopPersonTTS()
        stopAudioTrack()
    }
}